package com.example.server.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.server.web.domain.*;
import com.example.server.web.domain.Class;
import com.example.server.web.domain.page.PageQueryDto;
import com.example.server.web.domain.dto.QuestionnaireDto;
import com.example.server.web.domain.dto.QuestionnaireParamDto;
import com.example.server.web.domain.vo.StuQuestionnaireBriefVo;
import com.example.server.web.exception.CustomException;
import com.example.server.web.mapper.QuestionnaireMapper;
import com.example.server.web.service.*;
import com.example.server.web.utils.LoginUserUtil;
import com.example.server.web.utils.MyObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 作者
 * @since 2023-04-04
 */
@Service
public class QuestionnaireServiceImpl extends ServiceImpl<QuestionnaireMapper, Questionnaire> implements QuestionnaireService {
    @Autowired
    private QuestionnaireMapper questionnaireMapper;

    @Autowired
    private QuestionService questionService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private ClassService classService;

    @Autowired
    private StudentQuestionnaireService studentQuestionnaireService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private CourseClassTeacherService courseClassTeacherService;

    @Autowired
    private FactTableService factTableService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(Questionnaire questionnaire) {

        // questionnaire.setCreateById(LoginUserUtil.getLoginUser().getId());
        questionnaire.setCreateById(1L);
        LocalDateTime now = LocalDateTime.now();
        questionnaire.setCreateByTime(now);

        //查询课程
        Long courseId = questionnaire.getCourseId();
        Course course = courseService.getById(courseId);
        questionnaire.setCourseName(course.getCourseName());

        //查询班级
        Long classId = questionnaire.getClassId();
        Class aClass = classService.getById(classId);
        questionnaire.setClassName(aClass.getClassName());
        questionnaire.setJoinSum(aClass.getClassPersonNum());
        questionnaire.setCompleteSum(0);
        questionnaire.setEvalStatus("0");

        //查询课程-班级-老师关联信息
        String year = questionnaire.getYear();
        LambdaQueryWrapper<CourseClassTeacher> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseClassTeacher::getCourseId,courseId).eq(CourseClassTeacher::getClassId,classId).eq(CourseClassTeacher::getYear,year);
        CourseClassTeacher courseClassTeacher = courseClassTeacherService.getOne(queryWrapper);
        if (ObjectUtils.isEmpty(courseClassTeacher)){
            throw new CustomException("其课程不存在");
        }
        //更新关联课程状态
        courseClassTeacher.setStatus(1);
        boolean b = courseClassTeacherService.updateById(courseClassTeacher);
        if (!b){
            throw new CustomException("更新失败");
        }
        questionnaire.setYear(courseClassTeacher.getYear());
        questionnaire.setCctId(courseClassTeacher.getId());

        //**** 判断问卷是否存在名字
        if (StringUtils.isBlank(questionnaire.getQuestionnaireName())){
            //若为空，则取名字为：年份+班级+课程+问卷，比如：2022-2023 2020级软件2班 java课程问卷
            StringBuffer buffer = new StringBuffer();
            buffer.append(courseClassTeacher.getYear()+" ");
            buffer.append(aClass.getGrade()).append("级").append(aClass.getClassName()).append(" ");
            buffer.append(course.getCourseName()).append("课程问卷");
            //转为字符串并储存
            questionnaire.setQuestionnaireName(buffer.toString());
        }

        //新增问卷数据
        int insert = questionnaireMapper.insert(questionnaire);

        //判断是否添加成功
        if(insert != 1){
            throw new CustomException("问卷添加失败!");
        }

        //添加学生问卷记录
        //先查询班级的学生记录
        List<Student> studentList = studentService.getStudentsByClassId(aClass.getId());
        studentList.forEach(item ->{
            StudentQuestionnaire studentQuestionnaire = new StudentQuestionnaire();
            studentQuestionnaire.setQuestionnaireId(questionnaire.getId());
            studentQuestionnaire.setClassId(aClass.getId());
            studentQuestionnaire.setStatus(0);
            studentQuestionnaire.setUserId(item.getUserId());
            studentQuestionnaire.setCreateByTime(now);
            studentQuestionnaireService.save(studentQuestionnaire);
        });
    }

    @Override
    public QuestionnaireDto query(Long id) {
        QuestionnaireDto questionnaireDto = new QuestionnaireDto();
        Questionnaire questionnaire = questionnaireMapper.selectById(id);
        //复制属性
        BeanUtils.copyProperties(questionnaire,questionnaireDto);

        List<Question> questions = questionService.selectList(id);
        questionnaireDto.setQuestionList(questions);
        return questionnaireDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletes(List<Long> ids) {
        //先删除问卷
        questionnaireMapper.deleteBatchIds(ids);
        //再删除学生问卷记录
        LambdaQueryWrapper<StudentQuestionnaire> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(StudentQuestionnaire::getQuestionnaireId,ids);
        studentQuestionnaireService.remove(wrapper);
    }


    @Override
    public Map queryByClassId(Long classId, PageQueryDto pageQueryDto) {
        //查询本班级的问卷，并且按照时间倒序
        LambdaQueryWrapper<Questionnaire> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Questionnaire::getClassId,classId);
        wrapper.orderByDesc(Questionnaire::getCreateByTime);
        Page<Questionnaire> page = this.page(new Page<>(pageQueryDto.getPage(), pageQueryDto.getLimit()), wrapper);
        Map<String, Object> map = new HashMap<>();
        //设置数据
        map.put("list",page.getRecords());
        map.put("total",page.getTotal());
        return map;
    }

    @Override
    public Map queryByStu(PageQueryDto pageQueryDto) {
        //获得当前登录者id
        Long userId = LoginUserUtil.getLoginUser().getId();
        // LambdaQueryWrapper<Student> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // Student student = studentService.getOne(objectLambdaQueryWrapper.eq(Student::getUserId, userId));
        Map<String, Object> map = new HashMap<>();
        if(userId == null){
            throw new CustomException("用户id不存在");
        }
        //查询本人问卷
        Page<StuQuestionnaireBriefVo> stuQuestionnaireBriefVoPage = questionnaireMapper.queryByStu(pageQueryDto.build(), userId);
        map.put("list",stuQuestionnaireBriefVoPage.getRecords());
        map.put("total",stuQuestionnaireBriefVoPage.getTotal());
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addCompleteSum(Long questionnaireId) {
        //先判断问卷是否存在
        Questionnaire questionnaire = questionnaireMapper.selectById(questionnaireId);
        MyObjectUtils.throwExIfNull(questionnaire,"问卷为空");
        if (questionnaire.getCompleteSum()+1 > questionnaire.getJoinSum()){
            throw new CustomException("完成评测的人数超过参加评测的人数");
        }
        //评测状态
        String evalStatus = "0";
        //判断是否全部完成评测
        if (questionnaire.getCompleteSum()+1 == questionnaire.getJoinSum()){
            evalStatus = "1";
            //TODO 这里后面可以考虑使用队列
            //统计问卷数据
            factTableService.countQuestionnaireData(questionnaire);
        }
        //更新完成评测人数
        LambdaUpdateWrapper<Questionnaire> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Questionnaire::getId,questionnaireId);
        updateWrapper.set(Questionnaire::getCompleteSum,questionnaire.getCompleteSum()+1);
        updateWrapper.set(Questionnaire::getEvalStatus,evalStatus);
        boolean update = this.update(updateWrapper);
        if (!update) {
            throw new CustomException("更新问卷状态失败");
        }
        //更新课程-班级-教师关联表
        LambdaUpdateWrapper<CourseClassTeacher> updateWrapper2 = new LambdaUpdateWrapper<>();
        updateWrapper2.eq(CourseClassTeacher::getId,questionnaire.getCctId());
        // updateWrapper2.set(CourseClassTeacher::getCourseId,questionnaire.getCourseId());
        updateWrapper2.set(CourseClassTeacher::getStatus,Integer.valueOf(evalStatus)+1);
        boolean update2 = courseClassTeacherService.update(updateWrapper2);
        if (!update2) {
            throw new CustomException("更新失败");
        }
    }

    @Override
    public Map queryPage(QuestionnaireParamDto dto, PageQueryDto pageQueryDto) {
        //组装查询条件
        LambdaQueryWrapper<Questionnaire> wrapper = new LambdaQueryWrapper<>();
        //根据班级名称查询
        wrapper.like(StringUtils.isNotBlank(dto.getClassName()),Questionnaire::getClassName,dto.getClassName());
        //根据课程名称查询
        wrapper.like(StringUtils.isNotBlank(dto.getCourseName()),Questionnaire::getCourseName,dto.getCourseName());
        wrapper.orderByDesc(Questionnaire::getCreateByTime);
        Page<Questionnaire> page = this.page(new Page<>(pageQueryDto.getPage(), pageQueryDto.getLimit()), wrapper);
        Map<String, Object> map = new HashMap<>();
        //设置数据
        map.put("list",page.getRecords());
        map.put("total",page.getTotal());
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void recovery(String id) {
        //根据问卷id查询问卷
        LambdaQueryWrapper<Questionnaire> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Questionnaire::getCctId,id);
        Questionnaire questionnaire = questionnaireMapper.selectOne(queryWrapper);
        MyObjectUtils.throwExIfNull(questionnaire,"问卷不存在");

        //1、更新关联课程状态
        LambdaUpdateWrapper<CourseClassTeacher> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(CourseClassTeacher::getId,questionnaire.getCctId());
        // updateWrapper.set(CourseClassTeacher::getCourseId,questionnaire.getCourseId());
        updateWrapper.set(CourseClassTeacher::getStatus,"2");
        boolean update = courseClassTeacherService.update(updateWrapper);
        if (!update) {
            throw new CustomException("更新关联课程失败");
        }

        //2、更新问卷完成状态
        LambdaUpdateWrapper<Questionnaire> updateWrapper2 = new LambdaUpdateWrapper<>();
        updateWrapper2.eq(Questionnaire::getId,questionnaire.getId());
        updateWrapper2.set(Questionnaire::getEvalStatus,"1");
        boolean update2 = this.update(updateWrapper2);
        if (!update2) {
            throw new CustomException("更新问卷状态失败");
        }

        //查询学生的问卷记录（未填写）
        LambdaQueryWrapper<StudentQuestionnaire> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(StudentQuestionnaire::getQuestionnaireId,questionnaire.getId());
        queryWrapper2.eq(StudentQuestionnaire::getStatus,0);
        List<StudentQuestionnaire> studentQuestionnaireList = studentQuestionnaireService.getList(queryWrapper2);
        //将状态设为已完成
        studentQuestionnaireList.forEach(item -> item.setStatus(1));
        //3、更新学生问卷记录状态
        boolean update3 = studentQuestionnaireService.updateBatchById(studentQuestionnaireList);
        if (CollectionUtils.isNotEmpty(studentQuestionnaireList) && !update3){
            throw new CustomException("学生问卷记录更新失败");
        }

        //开始统计问卷
        factTableService.countQuestionnaireData(questionnaire);
    }
}
